package com.booleansoft.model.redirect;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;

/**
 * 实体类的抽象类, 实现了主键的生成配置策略, 及
 * <code>{@link Object#hashCode()}, {@link Object#equals(Object)}方法
 * 
 */
public abstract class SimpleEntity implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public boolean equals(Object obj) {
		if (obj == null)
			return false;
		if (!(obj instanceof SimpleEntity))
			return false;
		if (this == obj)
			return true;
		SimpleEntity that = (SimpleEntity) obj;
		if (this.getId() == null || that.getId() == null)
			return false;
		return (this.getId().equals(that.getId()));
	}

	@Override
	public int hashCode() {
		return 17 * 37 + (this.getId() == null ? 0 : this.getId().hashCode());
	}

	/**
	 * 克隆出一个<tt>id</tt>为<tt>null</tt>的实体对象
	 * 
	 * @return
	 * @throws BeansException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	@SuppressWarnings("unchecked")
	public <T> T cloneEntity() throws Exception {
		Class<? extends SimpleEntity> clazz = this.getClass();
		Object o = clazz.newInstance();
		BeanUtils.copyProperties(this, o, new String[] { "id" });
		return (T) o;
	}

	protected String id;

	public String getId() {
		return this.id;
	}

	public void setId(String id) {
		this.id = id;
	}

	/**
	 * 获取自身类型
	 * 
	 * @return
	 */
	public String getObjectType() { // 无须在数据库建立字段
		return this.getClass().getSimpleName().toLowerCase();
	}

	/**
	 * 把自身变成Map对象
	 * 
	 * @return
	 */
	public Map getBeanMap() {
		Field[] childfields = this.getClass().getDeclaredFields();
		Field[] superfields = this.getClass().getSuperclass()
				.getDeclaredFields();
		Field[] fields = new Field[childfields.length + superfields.length];
		System.arraycopy(superfields, 0, fields, 0, superfields.length);
		System.arraycopy(childfields, 0, fields, superfields.length,
				childfields.length);
		Map map = new HashMap();
		for (Field f : fields) {
			String fname = f.getName();
			String methodName = "get" + fname.substring(0, 1).toUpperCase()
					+ fname.substring(1);
			try {
				Method m = this.getClass().getMethod(methodName, null);
				m.setAccessible(true);
				Object o = m.invoke(this, null);
				map.put(fname, o);
			} catch (Exception e) {
				// 有些字段非映射没有get方法(hashValue),无需捕获异常
//				e.printStackTrace();
			}

		}
		return map;
	}

	public String toXMLString(){
		return toXMLString(0);
	}
	private String getSpaces(int n){
		StringBuffer sb=new StringBuffer();
		for(int i=0;i<n;i++){
			sb.append("  ");
		}
		return sb.toString();
	}
	public String toXMLString(int n){
		Map map=getBeanMap();
		StringBuffer sb=new StringBuffer();
		if(n==0){
			sb.append(getSpaces(n)).append("<").append(this.getObjectType()).append(">").append("\r\n");
		}
		Iterator iterator=map.entrySet().iterator();
		while(iterator.hasNext()){
			Map.Entry e=(Map.Entry)iterator.next();
			String key=(String)e.getKey();
			Object value=e.getValue();
			String showvalue="";
			if(value==null){
			}else if(value instanceof SimpleEntity){
				showvalue="\r\n"+((SimpleEntity)value).toXMLString(n+2)+getSpaces(n+1);
			}else{
				showvalue=""+value;
				showvalue=showvalue.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
			}
			sb.append(getSpaces(n+1)+"<"+key+">"+showvalue+"</"+key+">\r\n");
		}
		if(n==0){
			sb.append(getSpaces(n)).append("</").append(this.getObjectType()).append(">");
		}
		return sb.toString();
	}
	/**
	 * 把自身变成Map对象
	 * 
	 * @return
	 */
	public <T> T fromMap(Map detailmap) {
		Iterator iterator = detailmap.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry<String, Object> entry = (Map.Entry<String, Object>) iterator
					.next();
			Object obj = entry.getValue();
			if (obj instanceof BigDecimal) {
				BigDecimal b = (BigDecimal) obj;
				Double d = null;
				if (b != null)
					d = b.doubleValue();
				try {
					org.apache.commons.beanutils.BeanUtils.setProperty(this,
							entry.getKey().toLowerCase(), d);
				} catch (Exception e) {
				}
			} else {
				try {
					org.apache.commons.beanutils.BeanUtils.setProperty(this,
							entry.getKey().toLowerCase(), obj);
				} catch (Exception e) {
				}
			}
		}
		return (T) this;
	}
}